#include "oled.h"
#include "font6x8.h"
#include <string.h>

static I2C_HandleTypeDef *oled_i2c;

static void OLED_WriteCmd(uint8_t cmd)
{
    uint8_t buf[2] = {0x00, cmd};
    HAL_I2C_Master_Transmit(oled_i2c, OLED_ADDRESS, buf, 2, HAL_MAX_DELAY);
}

static void OLED_WriteData(uint8_t data)
{
    uint8_t buf[2] = {0x40, data};
    HAL_I2C_Master_Transmit(oled_i2c, OLED_ADDRESS, buf, 2, HAL_MAX_DELAY);
}

void OLED_Init(I2C_HandleTypeDef *hi2c)
{
    oled_i2c = hi2c;
    HAL_Delay(100);

    OLED_WriteCmd(0xAE); // Display Off
    OLED_WriteCmd(0x20); OLED_WriteCmd(0x10);
    OLED_WriteCmd(0xB0);
    OLED_WriteCmd(0xC8);
    OLED_WriteCmd(0x00);
    OLED_WriteCmd(0x10);
    OLED_WriteCmd(0x40);
    OLED_WriteCmd(0x81); OLED_WriteCmd(0x7F);
    OLED_WriteCmd(0xA1);
    OLED_WriteCmd(0xA6);
    OLED_WriteCmd(0xA8); OLED_WriteCmd(0x3F);
    OLED_WriteCmd(0xA4);
    OLED_WriteCmd(0xD3); OLED_WriteCmd(0x00);
    OLED_WriteCmd(0xD5); OLED_WriteCmd(0xF0);
    OLED_WriteCmd(0xD9); OLED_WriteCmd(0x22);
    OLED_WriteCmd(0xDA); OLED_WriteCmd(0x12);
    OLED_WriteCmd(0xDB); OLED_WriteCmd(0x20);
    OLED_WriteCmd(0x8D); OLED_WriteCmd(0x14);
    OLED_WriteCmd(0xAF); // Display On

    OLED_Clear();
}

void OLED_Clear(void)
{
    for(uint8_t page=0; page<8; page++)
    {
        OLED_WriteCmd(0xB0 + page);
        OLED_WriteCmd(0x00);
        OLED_WriteCmd(0x10);
        for(uint8_t col=0; col<128; col++)
            OLED_WriteData(0x00);
    }
}

void OLED_ShowChar(uint8_t x, uint8_t y, char chr)
{
    uint8_t c = chr - 32;
    if(x > 122) { x = 0; y++; }
    OLED_WriteCmd(0xB0 + y);
    OLED_WriteCmd(((x & 0xF0)>>4)|0x10);
    OLED_WriteCmd((x & 0x0F)|0x01);
    for(uint8_t i=0; i<6; i++)
        OLED_WriteData(F6x8[c][i]);
}

void OLED_ShowString(uint8_t x, uint8_t y, const char *str)
{
    while(*str)
    {
        OLED_ShowChar(x, y, *str++);
        x += 6;
        if(x > 122) { x = 0; y++; }
    }
}